if (meta < META_ASTERISK || meta > META_MINMAX_QUERY)
{
- if (OFLOW_MAX - *lengthptr < (PCRE2_SIZE)(code - orig_code))
+ if (*lengthptr > OFLOW_MAX ||
+ OFLOW_MAX - *lengthptr < (PCRE2_SIZE)(code - orig_code))
{
*errorcodeptr = ERR20; /* Integer overflow */
return 0;
*reqcuflagsptr = reqcuflags;
if (lengthptr != NULL)
{
- if (OFLOW_MAX - *lengthptr < length)
+ if (*lengthptr > MAX_PATTERN_SIZE ||
+ MAX_PATTERN_SIZE - *lengthptr < length)
{
*errorcodeptr = ERR20;
return 0;
{
code = *codeptr + 1 + LINK_SIZE + skipunits;
length += 1 + LINK_SIZE;
+
+ /* Move the accumulated length into *lengthptr, providing the next call to
+ compile_branch with as much space in &length and &code as the first did. */
+
+ if (*lengthptr > MAX_PATTERN_SIZE ||
+ MAX_PATTERN_SIZE - *lengthptr < length)
+ {
+ *errorcodeptr = ERR20;
+ cb->erroroffset = 0;
+ return 0;
+ }
+ *lengthptr += length;
+ length = 0;
}
else
{
#if defined SUPPORT_WIDE_CHARS
PCRE2_ASSERT((cb.char_lists_size & 0x3) == 0);
if (length > MAX_PATTERN_SIZE ||
- MAX_PATTERN_SIZE - length < (cb.char_lists_size / sizeof(PCRE2_UCHAR)))
+ BYTES2CU(cb.char_lists_size) > MAX_PATTERN_SIZE ||
+ MAX_PATTERN_SIZE - length < BYTES2CU(cb.char_lists_size))
#else
if (length > MAX_PATTERN_SIZE)
#endif
/* Align to 32 bit first. This ensures the
allocated area will also be 32 bit aligned. */
re_blocksize = (PCRE2_SIZE)CLIST_ALIGN_TO(re_blocksize, sizeof(uint32_t));
+#else
+ /* Already 32 bit aligned. */
#endif
+
+ /* We have bounded the length and BYTES2CU(char_lists_size) to
+ MAX_PATTERN_SIZE units, however (with 32-bit code units) char_lists_size
+ in bytes could still be extremely close to (or greater than) SIZE_MAX, so
+ we require another overflow check. */
+
+ if (cb.char_lists_size > PCRE2_SIZE_MAX - re_blocksize)
+ {
+ errorcode = ERR20;
+ cb.erroroffset = 0;
+ goto HAD_CB_ERROR;
+ }
+
re_blocksize += cb.char_lists_size;
}
#endif
+if (length > BYTES2CU(PCRE2_SIZE_MAX - re_blocksize))
+ {
+ /* Given the current value of 2^30 for MAX_PATTERN_SIZE, this block is only
+ reachable when both PCRE2_CODE_UNIT_WIDTH >= 16 and sizeof(size_t) is
+ 32 bits. */
+ errorcode = ERR20;
+ cb.erroroffset = 0;
+ goto HAD_CB_ERROR;
+ }
+
re_blocksize += CU2BYTES(length);
if (re_blocksize > ccontext->max_pattern_compiled_length)
goto HAD_CB_ERROR;
}
+if (sizeof(pcre2_real_code) > PCRE2_SIZE_MAX - re_blocksize)
+ {
+ errorcode = ERR20;
+ cb.erroroffset = 0;
+ goto HAD_CB_ERROR;
+ }
+
re_blocksize += sizeof(pcre2_real_code);
+
re = (pcre2_real_code *)
ccontext->memctl.malloc(re_blocksize, ccontext->memctl.memory_data);
if (re == NULL)
static class_ranges *
compile_optimize_class(uint32_t *start_ptr, uint32_t options,
- uint32_t xoptions, compile_block *cb)
+ uint32_t xoptions, int *errorcodeptr, compile_block *cb)
{
class_ranges* cranges;
uint32_t *ptr;
total_size = range_list_size +
((range_list_size >= 2) ? CHAR_LIST_EXTRA_SIZE : 0);
+if (total_size > (PCRE2_SIZE_MAX - sizeof(class_ranges)) / sizeof(uint32_t))
+ {
+ *errorcodeptr = ERR20;
+ cb->erroroffset = 0;
+ return NULL;
+ }
cranges = cb->cx->memctl.malloc(
sizeof(class_ranges) + total_size * sizeof(uint32_t),
cb->cx->memctl.memory_data);
-if (cranges == NULL) return NULL;
+if (cranges == NULL)
+ {
+ *errorcodeptr = ERR21;
+ cb->erroroffset = 0;
+ return NULL;
+ }
cranges->next = NULL;
cranges->range_list_size = (uint16_t)range_list_size;
{
if (lengthptr != NULL)
{
- cranges = compile_optimize_class(pptr, options, xoptions, cb);
+ cranges = compile_optimize_class(pptr, options, xoptions, errorcodeptr, cb);
if (cranges == NULL)
- {
- *errorcodeptr = ERR21;
return NULL;
- }
/* Caching the pre-processed character ranges. */
if (cb->next_cranges != NULL)
*lengthptr += 1 + LINK_SIZE;
#endif
- cb->char_lists_size += char_lists_size;
-
- char_lists_size /= sizeof(PCRE2_UCHAR);
+ PCRE2_ASSERT(BYTES2CU(cb->char_lists_size) <= MAX_PATTERN_SIZE);
- /* Storage space for character lists is included
- in the maximum pattern size. */
- if (*lengthptr > MAX_PATTERN_SIZE ||
- MAX_PATTERN_SIZE - *lengthptr < char_lists_size)
+ if (char_lists_size > PCRE2_SIZE_MAX - cb->char_lists_size ||
+ BYTES2CU(char_lists_size) > MAX_PATTERN_SIZE ||
+ BYTES2CU(cb->char_lists_size) > MAX_PATTERN_SIZE - BYTES2CU(char_lists_size))
{
*errorcodeptr = ERR20; /* Pattern is too large */
return NULL;
}
+
+ cb->char_lists_size += char_lists_size;
}
else
{
Each list is aligned to 32 bit with an optional unused
16 bit value at the beginning of the character list. */
+ PCRE2_ASSERT(char_lists_size <= PCRE2_SIZE_MAX - cb->char_lists_size);
+
cb->char_lists_size += char_lists_size;
data = (uint8_t*)cb->start_code - cb->char_lists_size;